package com.miku.sys.utils;

import java.io.File;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.miku.sys.config.Global;
import com.miku.utils.IOUtils;
import com.miku.utils.ImageUtil;
import com.miku.utils.Net;

public class ImageUtils {
	//当给定的图片宽或者高为这个值，表示为原始图片模版，即不会做resize操作
	public static final int sizeTemplateRaw = -1;
	
	private static Logger logger = LoggerFactory.getLogger(ImageUtils.class);
	
	//操作类型，定义裁切图片的操作方式
	public enum Operator{
		Resize,								//直接拉伸
		CenterCrop,						//中心裁图，会受尺寸不够影响
		CenterSquareCrop,			//中心裁图，方图
		CenterScaleCrop				//中心裁图，保证宽高比
	}
	
	/**
	 * 回复一个图片数据
	 * @param ws			提供的宽度数组表
	 * @param hs			提供的高度数组表
	 * @param dir			相对路径，比如系统人物头像，则提供：/sys/user
	 * @param name		提供的名字，比如系统人物头像，则提供："2"，或者比如帖子就提供：md5值
	 * @param idd			id多少
	 * @param n				第几套图片
	 */
	@SuppressWarnings("deprecation")
	public static void respImage(
			int w, int h, String dir, String name,  Operator operator,
			HttpServletRequest req, HttpServletResponse resp){
		//缓存1年的
		resp.setHeader("Cache-Control", "max-age=31536000"); //Cache-Control来控制页面的缓存与否,public:浏览器和缓存服务器都可以缓存页面信息；
		//response.setHeader("Cache-Control", "public");
		if((w < 0 || h < 0 || w >= 3000 || h >= 3000) && (w != sizeTemplateRaw && h != sizeTemplateRaw)) {
			resp.setStatus(HttpStatus.SC_NOT_FOUND);
			return;
		}
		
		//如果宽或者高有一个为-1，就表示是原始图片
		boolean rawSize = w == sizeTemplateRaw || h == sizeTemplateRaw;
		String img = null;
		if(rawSize){
			//如果是按照原始尺寸去看，就没有几套几套的问题了，直接取原名
			img = String.format("%s%s/%s.jpg", Global.getImageDir(), dir, name);
		}else{
			img = String.format("%s%s/%s_%dx%d.jpg", Global.getImageDir(), dir, name, w, h);
		}
		
		if(IOUtils.fileExists(img)){
			File f = new File(img);
			String lastModifed = req.getHeader("If-Modified-Since");
			Date t = null;
			if(lastModifed != null){
				try{
					t = new Date(lastModifed);
				}catch(Exception e){}
			}
			
			if(t == null) t = new Date();
			
			//如果用户端图片修改时间在服务器之前，表示要更新
			if(t.after(new Date(f.lastModified()))){
				resp.setDateHeader("Last-Modified", f.lastModified()); //Last-Modified:页面的最后生成时间
				resp.setContentType("image/jpg");
				IOUtils.respFile(img, resp);
			}else{
				resp.setDateHeader("Last-Modified", f.lastModified()); //Last-Modified:页面的最后生成时间
				resp.setContentType("image/jpg");
				resp.setStatus(HttpStatus.SC_NOT_MODIFIED);
			}
			return;
		}else if(rawSize){
			//如果要求是原图，那么提示不存在
			//logger.debug("文件不存在：" + img);
			resp.setStatus(HttpStatus.SC_NOT_FOUND);
			return;
		}
		
		String baseImage = String.format("%s%s/%s.jpg", Global.getImageDir(), dir, name);
		File f = new File(baseImage);
		//如果基本图片不存在
		if(!f.exists()){
			logger.debug("文件不存在：" + f.getAbsolutePath());
			resp.setStatus(HttpStatus.SC_NOT_FOUND);
			return;
		}
		
		boolean operIsOK = false;
		if(operator == Operator.Resize){
			operIsOK = ImageUtil.resize(baseImage, img, w, h) ;
		}else if(operator == Operator.CenterCrop){
			operIsOK = ImageUtil.cropCenter(baseImage, img, w, h);
		}else if(operator == Operator.CenterSquareCrop){
			operIsOK = ImageUtil.cropCenterSquare(baseImage, img, Math.max(w, h));
		}else if(operator == Operator.CenterScaleCrop){
			operIsOK = ImageUtil.cropCenterScale(baseImage, img, w, h);
		}
		
		if(!operIsOK){
			logger.debug("resize图像失败：" + baseImage + "，到：" + img + "，w =  " + w + "，h = " + h);
			resp.setStatus(HttpStatus.SC_INTERNAL_SERVER_ERROR);
		}else{
			f = new File(img);
			resp.setDateHeader("Last-Modified", f.lastModified()); //Last-Modified:页面的最后生成时间
			
			resp.setContentType("image/jpg");
			IOUtils.respFile(img, resp);
		}
	}
	
	/**
	 * 获取业务相关图片路径，返回c:/image/business
	 * @return
	 */
	public static String getBusinessDir(){
		return Global.getImageDir() + "/business";
	}
	
	/**
	 * 获取帖子相关图片路径，返回c:/image/business/posts
	 * @return
	 */
	public static String getPostsDir(){
		return getBusinessDir() + "/posts";
	}
	
	/**
	 * 获取帖子相关图片路径，返回c:/image/business/recproduct
	 * @return
	 */
	public static String getRecproductDir(){
		return getBusinessDir() + "/recproduct";
	}
	
	
	/**
	 * 获取用户头像的路径
	 * @param uid
	 * @return
	 */
	public static String getUserImagePath(int uid){
		return String.format("%s/sys/user/%d.jpg", Global.getImageDir(), uid);
	}
	
	/**
	 * 获取用户头像微信的路径
	 * @param uid
	 * @return
	 */
	public static String getUserImageSuffixPath(int uid, String suffix){
		return String.format("%s/sys/user/%d_%s.jpg", Global.getImageDir(), uid, suffix);
	}
	
	/**
	 * 下载用户头像，启动一个线程来实现，那么就不会卡住当前进程
	 * @param uid						用户的id
	 * @param fromSuffix			来自于的后缀，会保存一个副本，比如qq的图片，那么指定为qq，保存会是：/image/sys/user/3_qq.jpg，如果不需要
	 * 												保存副本，直接给null
	 * @param url						图像的url地址
	 */
	public static void postDownloadUserPortraitImage(final int uid, final String fromSuffix, final String url){
		new Thread(){
			@Override
			public void run() {
				downloadUserPortraitImage(uid, fromSuffix, url);
			};
		}.start();
	}
	
	/**
	 * 下载用户头像，启动一个线程来实现，那么就不会卡住当前进程
	 * @param uid						用户的id
	 * @param fromSuffix			来自于的后缀，会保存一个副本，比如qq的图片，那么指定为qq，保存会是：/image/sys/user/3_qq.jpg，如果不需要
	 * 												保存副本，直接给null
	 * @param url						图像的url地址
	 */
	public static void downloadUserPortraitImage(int uid, String fromSuffix, String url){
		if(StringUtils.isEmpty(url)) return;
		
		String rawImage = getUserImagePath(uid);
		if(Net.queryGetToFile(url, rawImage)){
			
			//不需要副本，直接给null
			if(fromSuffix != null)
				IOUtils.copyTo(rawImage, getUserImageSuffixPath(uid, fromSuffix));
		}else
			logger.debug("下载图片(到 {})失败：" + url, rawImage);
	}
	
	/**
	 * 判断一个用户的头像有没有，如果有返回true
	 * @param uid
	 * @return
	 */
	public static boolean userPortraitExists(int uid){
		return IOUtils.fileExists(getUserImagePath(uid));
	}
}